package com.mouse.magent.proxy.handler;

import com.mouse.magent.common.handler.CommonHandler;
import com.mouse.magent.common.net.TcpClient;
import com.mouse.magent.common.util.HttpUtil;
import io.netty.channel.*;
import io.netty.handler.codec.bytes.ByteArrayDecoder;
import io.netty.handler.codec.bytes.ByteArrayEncoder;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.util.ReferenceCountUtil;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class HttpServiceHandler extends CommonHandler {
    //Complete方法中刷新数据
    private ChannelFuture cf;
    private String host;
    private int port;

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        try {
            handler(ctx, msg);
        } catch (Exception e) {
            ReferenceCountUtil.release(msg);
        }
    }


    private void handler(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof FullHttpRequest) {
            FullHttpRequest request = (FullHttpRequest) msg;
            String hostHeader = request.headers().get("host");
            String[] hostSplit = hostHeader.split(":");
            host = hostSplit[0];
            port = 80;
            if (hostSplit.length > 1) {
                port = Integer.valueOf(hostSplit[1]);
            } else {
                if (request.uri().startsWith("https")) port = 443;
            }
            String methodName = request.method().name();
            log.info("Method:{} url:{}", methodName, request.uri());
            if ("CONNECT".equalsIgnoreCase(methodName)) {//HTTPS建立代理握手
                ReferenceCountUtil.release(msg);
                ctx.writeAndFlush("HTTP/1.1 200 OK\r\n\r\n".getBytes());
                ctx.pipeline().remove("decoder");
                ctx.pipeline().remove("httpObject");
                return;
            }
            cf = connectServer(host, port, ctx, HttpUtil.toBuf(request));
        } else { // https 只转发数据，不做处理
            if (cf == null) {
                //连接至目标服务器
                cf = connectServer(host, port, ctx, msg);
            } else {
                cf.channel().writeAndFlush(msg);
            }
        }
    }

    private ChannelFuture connectServer(String host, int port, ChannelHandlerContext ctx, Object msgByte) throws Exception {
        //连接至目标服务器
        TcpClient tcpClient = new TcpClient();
        ChannelFuture channelFuture = tcpClient.connectCustom(host, port, new ChannelInitializer() {
            @Override
            protected void initChannel(Channel channel) throws Exception {
                HttpProxyHandler localProxyHandler = new HttpProxyHandler(ctx);
                channel.pipeline().addLast(new ByteArrayDecoder(), new ByteArrayEncoder(), localProxyHandler);
            }
        });
        channelFuture.addListener((ChannelFutureListener) future -> {
            if (future.isSuccess()) {
                future.channel().writeAndFlush(msgByte);
            } else {
                ctx.channel().close();
            }
        });
        return channelFuture;
    }


    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        try {
            if (cf != null) cf.channel().close();
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }
}


